#include "app.h"

char UpgradeDoneFlag = 0;
uint8_t send_start_buf[6] = {0xA5, 0x5A, 0x06, 0x00, 0x10, 0x01};
uint8_t get_package_buf[14] = {0xA5, 0x5A, 0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 2022change
// uint8_t send_over_buf[9] = {0xA5, 0x5A, 0x09, 0x00, 0x12, 0x00, 0x00, 0x00,0x00};//2022change

uint32_t FlashPtr;
typedef void (*pFunction)(void);
pFunction Jump_To_Application;

uint32_t packagesSize;
uint8_t rx2_frame_OK;
uint8_t rx2_buff[rx2_buffsize];
uint16_t rx2count;
uint8_t wifi_connect_flg = 0;
uint16_t time_flg = 0;
uint8_t version[4] = {0}; // 2022change
uint32_t current_package; // 当前升级包
uint8_t upgrade_hand_flg = 0;
uint16_t lastFrameCnt = 0; // 最后一帧字节数
uint8_t flash_array[BinPerFrameSize];

void WIFI_INIT()
{
	rcu_periph_clock_enable(RCU_GPIOB);
	gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
	gpio_bit_reset(GPIOB, GPIO_PIN_12);
	delay_1ms(200);
	gpio_bit_set(GPIOB, GPIO_PIN_12);
}
//-----------------------------------------------------------------//
// 函数名称：
// 函数功能：
// 返 回 值：压力垫
//-----------------------------------------------------------------//
void usart2_config()
{
	/* enable GPIO clock */
	rcu_periph_clock_enable(RCU_GPIOB);

	/* enable USART clock */
	rcu_periph_clock_enable(RCU_USART2);

	/* connect port to USARTx_Tx */
	gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);

	/* connect port to USARTx_Rx */
	gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_11);

	/* USART configure */
	usart_deinit(USART2);
	usart_baudrate_set(USART2, 115200U);
	usart_word_length_set(USART2, USART_WL_8BIT);
	usart_stop_bit_set(USART2, USART_STB_1BIT);
	usart_parity_config(USART2, USART_PM_NONE);
	usart_hardware_flow_rts_config(USART2, USART_RTS_DISABLE);
	usart_hardware_flow_cts_config(USART2, USART_CTS_DISABLE);
	usart_receive_config(USART2, USART_RECEIVE_ENABLE);
	usart_transmit_config(USART2, USART_TRANSMIT_ENABLE);
	usart_enable(USART2);

	/* USART interrupt configuration */
	nvic_irq_enable(USART2_IRQn, 0, 0);
	/* enable USART2 receive interrupt */
	usart_interrupt_enable(USART2, USART_INT_RBNE);
}
//-----------------------------------------------------------------//
// 函数名称：
// 函数功能：
// 返 回 值：压力垫
//-----------------------------------------------------------------//
void timer5_init(uint16_t arr, uint16_t psc)
{
	timer_parameter_struct timer_initpara;
	rcu_periph_clock_enable(RCU_TIMER5);
	timer_deinit(TIMER5);

	timer_initpara.prescaler = psc; /* 时钟预分频系数 */
	timer_initpara.period = arr;	/* 自动重装载值 */
	timer_init(TIMER5, &timer_initpara);
	timer_enable(TIMER5);

	nvic_irq_enable(TIMER5_IRQn, 3, 3);			  /* 中断设置，抢占优先级3，子优先级3 */
	timer_interrupt_enable(TIMER5, TIMER_INT_UP); /* 使能更新中断 */
}

void boot_usart2send(uint8_t *s, uint16_t lenth)
{
	uint16_t i;
	for (i = 0; i < lenth; i++)
	{
		usart_data_transmit(USART2, (uint8_t)s[i]);
		while (RESET == usart_flag_get(USART2, USART_FLAG_TBE))
			;
	}
}
//-----------------------------------------------------------------//
// 函数名称：
// 函数功能：
// 返 回 值：压力垫
//-----------------------------------------------------------------//
uint32_t OPENBL_CRC32_MPEG_2(uint8_t *data, uint32_t length)
{
	uint32_t i;
	uint32_t crc = 0xffffffff, j = 0;

	while ((length--) != 0)
	{
		crc ^= (uint32_t)data[j] << 24;
		j++;
		for (i = 0; i < 8; ++i)
		{
			if ((crc & 0x80000000) != 0)
			{
				crc = (crc << 1) ^ 0x04C11DB7;
			}
			else
			{
				crc <<= 1;
			}
		}
	}
	return crc;
}
//-----------------------------------------------------------------//
// 函数名称：
// 函数功能：
// 返 回 值：压力垫
//-----------------------------------------------------------------//
void CRC_usart2send(uint8_t *data, uint32_t length)
{
	uint32_t crc_temp, i;
	uint8_t crc[4];

	crc_temp = OPENBL_CRC32_MPEG_2(data, length);
	crc[0] = (uint8_t)crc_temp;
	crc[1] = (uint8_t)(crc_temp >> 8);
	crc[2] = (uint8_t)(crc_temp >> 16);
	crc[3] = (uint8_t)(crc_temp >> 24);
	for (i = 0; i < length; i++)
	{
		usart_data_transmit(USART2, (uint8_t)data[i]);
		while (RESET == usart_flag_get(USART2, USART_FLAG_TBE))
			;
	}
	for (i = 0; i < 4; i++)
	{
		usart_data_transmit(USART2, (uint8_t)crc[i]);
		while (RESET == usart_flag_get(USART2, USART_FLAG_TBE))
			;
	}
}
//-----------------------------------------------------------------//
// 函数名称：
// 函数功能：
// 返 回 值：压力垫
//-----------------------------------------------------------------//
uint8_t flashWrite(uint8_t *data, uint_fast8_t length)
{
	static uint8_t buffer;
	uint16_t temp, i;
	uint_fast8_t index;
	uint32_t flashPtr1;

	if (length == 0)
		return 0;
	flashPtr1 = FlashPtr;
	fmc_unlock();

	index = 0;

	do
	{
		if (flashPtr1 & 1)
		{
			flashPtr1--;
			temp = buffer;
		}
		else
		{
			temp = data[index++];
		};

		temp |= data[index++] << 8;

		fmc_halfword_program(flashPtr1, temp);
		flashPtr1 += sizeof(uint16_t);

	} while ((length - index) >= 2);

	for (i = 0; i < length; i++) // 读出flash校验是否写错
	{
		if (data[i] != *(uint8_t *)(FlashPtr + i))
			return 1; // 有错
	}
	fmc_lock();
	FlashPtr += length;
	return 0;
}
//-----------------------------------------------------------------//
// 函数名称：
// 函数功能：
// 返 回 值：压力垫
//-----------------------------------------------------------------//
void page_flashErase(uint32_t pagecount) // 形参为包数量
{
	uint16_t i, ErasepageNO;
	ErasepageNO = pagecount / 2048 + 1; // 2048个字节一页
	fmc_unlock();
	for (i = 0; i < ErasepageNO; i++)
	{
		fmc_page_erase(FLASH_APP_ADDR + 2048 * i);
	}
	fmc_lock();
}

int check_stack_head(unsigned long execAdr)
{
	// MBL_APP_EXEC_ADR为新程序的起始地址，检查栈顶地址是否合法，即栈顶地址是否为0x2000xxxx（内置SRAM）
	if (((*(__IO uint32_t *)execAdr) & 0x2FFE0000UL) == 0x20000000UL)
		return 0;
	else
		return -1;
}
//-----------------------------------------------------------------//
// 函数名称：
// 函数功能：
// 返 回 值：压力垫
//-----------------------------------------------------------------//
void flash_write_version(uint8_t *version) // version为4个字节
{
	// 需要flash已解锁
	uint32_t value;
	value = *(__IO uint32_t *)version;
	fmc_word_program(FLASH_VERSION_ADDR, value);
}
//-----------------------------------------------------------------//
// 函数名称：
// 函数功能：
// 返 回 值：压力垫
//-----------------------------------------------------------------//
void execute_app()
{
	uint32_t JumpAddress = 0;

	timer_deinit(TIMER5);
	usart_deinit(USART2);
	rcu_deinit();

	JumpAddress = *(__IO uint32_t *)(FLASH_APP_ADDR + 4); // 用户代码区第二个字存储为新程序起始地址（新程序复位向量指针）
	Jump_To_Application = (pFunction)JumpAddress;
	__set_MSP(*(__IO uint32_t *)FLASH_APP_ADDR); // 初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
	Jump_To_Application();						 // 设置PC指针为新程序复位中断函数的地址
}
//-----------------------------------------------------------------//
// 函数名称：
// 函数功能：
// 返 回 值：压力垫
//-----------------------------------------------------------------//
char OTA_DoneFlag = 0;
void upgrade_menu(void)
{
	uint8_t error;

	//	if(time_flg==0) //超时重发
	//	{
	//		if(wifi_connect_flg == 0)//没有连接上
	//		{
	//			CRC_usart2send(send_start_buf, 6);
	//
	//		}
	//		else
	//		{
	//			upgrade_hand_flg = 0x01;
	//		}
	//		time_flg = resent_time;//重新计时
	//	}

	switch (upgrade_hand_flg)
	{
	case 0x01:					 // 获取数据包
		upgrade_hand_flg = 0x00; // 获取数据包标志位置0
		get_package_buf[6] = (uint8_t)current_package;
		get_package_buf[7] = (uint8_t)(current_package >> 8); // 2022change
		get_package_buf[8] = (uint8_t)(current_package >> 16);
		get_package_buf[9] = (uint8_t)(current_package >> 24);
		//				time_flg = resent_time;//重新计时
		if(!OTA_DoneFlag)
			CRC_usart2send(get_package_buf, 9); // 2022change

		break;
	case 0x02:											  // 写入数据包
		error = flashWrite(flash_array, BinPerFrameSize); // 写入flash,固定一包写256个字节
		if (1 == error)									  // 写入错误重启，重新升级
		{
			NVIC_SystemReset();
		}

		if (0 == lastFrameCnt)
		{
			current_package += BinPerFrameSize;
			upgrade_hand_flg = 0x01;   // 获取数据包标志位置0
			get_package_buf[5] = 0x01; // 回复OK
		}
		//				else if(UpgradeDoneFlag)	//最后一帧发完
		//				{
		//					current_package+=lastFrameCnt;
		//					upgrade_hand_flg = 0x44; //flash完成标志位
		//					get_package_buf[5] = 0x03;//回复完成
		//				}
		break;
	case 0x44: // Execute The New Program Enter 'D'
		// MBL_APP_EXEC_ADR为新程序的起始地址，检查栈顶地址是否合法，即栈顶地址是否为0x2000xxxx（内置SRAM）
		if (check_stack_head(FLASH_APP_ADDR) == 0 && !OTA_DoneFlag)
		{
			//					send_over_buf[5] = version[0];
			//					send_over_buf[6] = version[1];
			//					send_over_buf[7] = version[2];
			//					send_over_buf[8] = version[3];//2022change

			get_package_buf[6] = (uint8_t)current_package;
			get_package_buf[7] = (uint8_t)(current_package >> 8);
			get_package_buf[8] = (uint8_t)(current_package >> 16);
			get_package_buf[9] = (uint8_t)(current_package >> 24);  
			CRC_usart2send(get_package_buf, 9); // 发送完成升级
			OTA_DoneFlag = 1; 
			delay_1ms(2);
		}

		break;
	case 0x1E: // wifi发的东西

		break;
	default:
		break;
	}
	if (UpgradeDoneFlag) // 最后一帧发完
	{
		current_package += lastFrameCnt;
		upgrade_hand_flg = 0x44;   // flash完成标志位
		get_package_buf[5] = 0x03; // 回复完成
	}
}
uint16_t PackageNum = 0;
void boot_ReceiveHdl()
{
	uint32_t crcCal, i;

	uint8_t crcGet[4];
	uint32_t packageNO;
	if (rx2_frame_OK)
	{
		switch (rx2_buff[4])
		{

		case 0x10:					   // 已进入升级模式
			get_package_buf[5] = 0x01; // 回复OK
			CRC_usart2send(send_start_buf, 6);
			break;
		case 0x11: // 包头数据
			// 获取版本号
			version[0] = rx2_buff[5];
			version[1] = rx2_buff[6];
			version[2] = rx2_buff[7];
			version[3] = rx2_buff[8]; // 2022change
			// 更新请求帧的版本号
			//			get_package_buf[5] = version[0];
			//			get_package_buf[6] = version[1];
			//			get_package_buf[7] = version[2];
			//			get_package_buf[8] = version[3];//2022change
			// 获取bin字节数
			packagesSize = (uint32_t)(rx2_buff[12]) << 24 | (uint32_t)(rx2_buff[11]) << 16 | (uint32_t)(rx2_buff[10]) << 8 | rx2_buff[9];
			page_flashErase(packagesSize); // 擦除需要占用的flash空间
			FlashPtr = FLASH_APP_ADDR;
			current_package = 0; // 当前数据包从0开始
			lastFrameCnt = 0;
			upgrade_hand_flg = 0x01; // 开始获取包标志位
			wifi_connect_flg = 1;	 // 通讯连接上
			break;
		case 0x12: // 升级包数据
			// 获取当前包序号
			packageNO = (uint32_t)(rx2_buff[8]) << 24 | (uint32_t)(rx2_buff[7]) << 16 | (uint32_t)(rx2_buff[6]) << 8 | rx2_buff[5];
			// 获取CRC
			crcGet[0] = rx2_buff[rx2count - 4];
			crcGet[1] = rx2_buff[rx2count - 3];
			crcGet[2] = rx2_buff[rx2count - 2];
			crcGet[3] = rx2_buff[rx2count - 1];

			crcCal = OPENBL_CRC32_MPEG_2(rx2_buff, rx2count - 4);

			if ((*(__IO uint32_t *)crcGet == crcCal) && (packageNO == current_package)) // CRC校验合格、包序号正确
			{
				for (i = 0; i < BinPerFrameSize; i++)
				{
					flash_array[i] = rx2_buff[9 + i];
				}
				upgrade_hand_flg = 0x02;											  // 开始写入flash
				if (packagesSize - ((PackageNum) * 512) < 512 && (packagesSize != 0)) // 36
				{
					UpgradeDoneFlag = 1;
					lastFrameCnt = packagesSize - ((PackageNum) * 512);
					if (lastFrameCnt < BinPerFrameSize)
					{
						memset(&flash_array[lastFrameCnt], 0xff, BinPerFrameSize - lastFrameCnt);
					}
				}
				PackageNum++;
				//				if(((rx2count-13+current_package)>=packagesSize))//判断最后一帧多少字节
				//				{
				//					lastFrameCnt=rx2count-13;
				//					if(lastFrameCnt<BinPerFrameSize)
				//					{
				//						memset(&flash_array[lastFrameCnt],0xff,BinPerFrameSize-lastFrameCnt);
				//					}
				//				}
			}
			else
			{
				upgrade_hand_flg = 0x01;   // 开始获取包标志位--重新开始获取
				get_package_buf[5] = 0x02; // 回复重新获取
			} 
			break;
		case 0x13: //复位
			if(OTA_DoneFlag){ 
				fmc_unlock();
				fmc_page_erase(FLASH_DATA_FLAG_ADDR); /*擦除升级标志位*/
				flash_write_version(version);
				fmc_lock();
				execute_app(); /*执行用户程序*/
			}
			break;
		}
		rx2count = 0;
		rx2_frame_OK = 0;
	}
	//	if(packagesSize - ((PackageNum) * 512) < 512 && (packagesSize!=0)) //36
	//		UpgradeDoneFlag = 1;
}

/***************定时器中断****************************/
void TIMER5_IRQHandler()
{
	static uint16_t count_ms = 0;

	if (count_ms++ > 1000) // 1s
	{
		if (time_flg)
			time_flg--;
		count_ms = 0;
	}

	timer_flag_clear(TIMER5, TIMER_FLAG_UP);
}
/***************串口中断****************************/
// void USART2_IRQHandler(void)
//{
//   static uint8_t rx_begin=0;
//	uint16_t templen=0;
//	if(RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_RBNE))
//	{
//		if(rx2_frame_OK==1) //没处理完再发就丢弃
//		{
//			usart_data_receive(USART2);
//			return;
//		}
//		/* read one byte from the receive data register */
//		rx2_buff[rx2count++]= (uint8_t)usart_data_receive(USART2);
//
//		if(rx2count>=2)
//		{
//			if(0xa5==rx2_buff[0]&&0x5a==rx2_buff[1])
//				rx_begin=1;								//帧头正确
//			else if(0xa5==rx2_buff[0])
//				rx2count=1;
//			else
//				rx2count=0;
//		}
//		if(rx2count>=rx2_buffsize) //防止溢出
//			rx2count=0;
//
//		if(rx_begin && rx2count>=4)
//		{
//			templen=(uint16_t)(rx2_buff[3])<<8|rx2_buff[2];
//			if(rx2count>=(4+templen))
//			{
//				rx2_frame_OK=1;
//				rx_begin=0;

//			}
//		}

//   }
//}
//-----------------------------------------------------------------//
// 函数名称：
// 函数功能：
// 返 回 值：压力垫
//-----------------------------------------------------------------//
void USART2_IRQHandler(void)
{
	static uint8_t rece_step = 0;
	static uint16_t templen = 0;
	uint8_t receive;
	if (RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_RBNE))
	{
		receive = (uint8_t)usart_data_receive(USART2);
		rx2_buff[rx2count++] = receive;
		if (rx2_frame_OK == 1) // 没处理完再发就丢弃
		{
			usart_data_receive(USART2);
			return;
		}
		switch (rece_step)
		{
		case 0:
			if (receive == 0xa5)
			{
				rece_step = 1;
				rx2count = 1;
			}
			else
				rx2count = 0;
			break;
		case 1:
			if (receive == 0x5a)
			{

				rx2_buff[0] = 0xa5;
				rx2_buff[1] = 0x5a;
				rx2count = 2;
				rece_step = 2;
			}
			else
			{
				if (receive == 0xA5)
				{
					rece_step = 1;
					rx2count = 1;
				}
				else
					rece_step = 0;
			}
			break;

		case 2:
			if (rx2count >= 4)
			{
				templen = (uint16_t)(rx2_buff[3]) << 8 | rx2_buff[2];

				rece_step = 3;
			}
			break;
		case 3:
			if ((templen >= rx2_buffsize) || rx2count >= rx2_buffsize)
			{
				rece_step = 0;
				rx2count = 0;
			}
			else if (rx2count >= (4 + templen))
			{
				rx2_frame_OK = 1;
				rece_step = 0;
			}

			break;
		}
	}
}
